package com.cavy.platform.server.domain.message;

import com.cavy.platform.server.domain.AgentOnline;
import com.cavy.platform.server.domain.job.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.websocket.Session;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 唐旭
 * @Date 2018/7/24
 */
@Service
@Slf4j
public class JobRunningMessageHandler extends AbstractMessageHandlerImpl<JobRunningMessage> implements MessageHandler {
    private static final List<Class<? extends JobAction>> JOB_ACTION_SET = new ArrayList<>();
    private static final List<JobRunningMessageSubscribers> TYPE_SET = new ArrayList<>();

    static {
        JOB_ACTION_SET.add(PendingJob.class);
        JOB_ACTION_SET.add(RunningJob.class);
        JOB_ACTION_SET.add(TimeoutErrorJob.class);
        JOB_ACTION_SET.add(EndJob.class);
        JOB_ACTION_SET.add(ErrorJob.class);

        for (Class<? extends JobAction> jobActionClazz : JOB_ACTION_SET) {
            Method[] methods = jobActionClazz.getMethods();
            for (Method method : methods) {
                JobMessageSubscribe annotation = method.getAnnotation(JobMessageSubscribe.class);
                if (annotation != null) {
                    Class<?>[] parameterTypes = method.getParameterTypes();
                    if (parameterTypes.length != 1) {
                        continue;
                    }
                    Class<?> parameterType = parameterTypes[0];
                    if (JobRunningMessage.class.isAssignableFrom(parameterType)) {
                        TYPE_SET.add(new JobRunningMessageSubscribers(jobActionClazz, method, parameterType.getSimpleName()));
                    }
                }
            }
        }

    }

    @Override
    public boolean support(String type) {
        for (JobRunningMessageSubscribers item : TYPE_SET) {
            if (item.support(type)) {
                return true;
            }
        }
        return false;
    }

    @Override
    protected Class<JobRunningMessage> getTypeClass() {
        return JobRunningMessage.class;
    }

    //容器执行失败消息处理
    //1,检查此容器是否可以失败
    //2.1,如果不允许失败,则job状态变更(失败)
    //2.2,如果允许失败,则job状态变更(警告)
    @Override
    public void handler(Session session, JobRunningMessage message, AgentOnline agent) {
        try {
            for (JobRunningMessageSubscribers subscribers : TYPE_SET) {
                if (subscribers.support(message.getType())) {
                    JobAction jobAction = subscribers.getClazz().newInstance();
                    jobAction.load(message);
                    log.debug("找到消息处理器:{},方法:{},消息:{}", subscribers.getClazz(), subscribers.getMethod(), message);
                    subscribers.getMethod().invoke(jobAction, message);
                }
            }
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
            log.error("处理消息发生错误,错误类型:{},错误消息:{}", e.getClass().getName(), e.getMessage());
            throw new RuntimeException(e);
        }
    }
}
